home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / menu.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  8KB  |  310 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17.  
  18. #include <X11/Xaw/MenuButton.h>
  19. #include <X11/Xaw/SimpleMenu.h>
  20. #include <X11/Xaw/SmeBSB.h>
  21. #include <X11/Xaw/SmeLine.h>
  22. #include <X11/Xaw/Form.h>
  23. #include <stdio.h>
  24. #include "menu.h"
  25.  
  26. #include "bitmaps/checkmark.xbm"
  27. #include "bitmaps/pullright.xbm"
  28.  
  29. #define MAX_GROUPS    4
  30.  
  31. typedef struct group_s {
  32.     int        size;
  33.     Widget        group[16];
  34.     struct group_s    *next;
  35. } GroupList;
  36.  
  37. typedef struct rightlist_s {
  38.     Widget            widget;
  39.     Widget            shell;
  40.     struct rightlist_s    *next;
  41. } RightList;
  42.  
  43. static GroupList    *groupHead = NULL;
  44. static RightList    *rightHead = NULL;
  45. static Pixmap        checkBitmap = None, pullBitmap = None;
  46.  
  47. static void pullRightAction(Widget, XEvent *, String *, Cardinal *);
  48.  
  49. static GroupList    *findGroup(Widget w)
  50. {
  51.     GroupList    *cur = groupHead;
  52.     int        i;
  53.  
  54.     if (w == None)
  55.         return NULL;
  56.  
  57.     while (cur != NULL) {
  58.         for (i = 0; i < cur->size; i++)
  59.             if (cur->group[i] == w)
  60.                 return cur;
  61.         cur = cur->next;
  62.     }
  63.     return NULL;
  64. }
  65.  
  66. static void initMenu(Widget w)
  67. {
  68.     static XtActionsRec    act = { "popup-menu-pullright", (XtActionProc)pullRightAction };
  69.  
  70.     if (checkBitmap != None)
  71.         return;
  72.  
  73.     checkBitmap = XCreateBitmapFromData(XtDisplay(w),
  74.                 DefaultRootWindow(XtDisplay(w)),
  75.                 (char *)checkmark_bits,
  76.                 checkmark_width, checkmark_height);
  77.     pullBitmap = XCreateBitmapFromData(XtDisplay(w),
  78.                 DefaultRootWindow(XtDisplay(w)),
  79.                 (char *)pullright_bits,
  80.                 pullright_width, pullright_height);
  81.  
  82.     XtAppAddActions(XtWidgetToApplicationContext(w), &act, 1);
  83. }
  84.  
  85. static void destroy(Widget w, XtPointer data, XtPointer junk)
  86. {
  87.     XtFree((XtPointer)data);
  88. }
  89.  
  90. static void pullRightAction(Widget w, XEvent *event, String *params, Cardinal *nparams)
  91. {
  92.     Dimension    width, height;
  93.     int        x, y;
  94.     RightList    *cur;
  95.     Widget        cw = XawSimpleMenuGetActiveEntry(w);
  96.  
  97.     if (cw == None || event->type != MotionNotify)
  98.         return;
  99.  
  100.     x = event->xmotion.x;
  101.     y = event->xmotion.y;
  102.  
  103.     XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
  104.     if (x < 0 || x >= width || y < 0 || y >= height)
  105.         return;
  106.  
  107.     /*
  108.     **  Only the second half of the menu is sensitve to pulls
  109.     */
  110.     if (x < width / 2)
  111.         return;
  112.  
  113.     for (cur = rightHead; cur != NULL && cur->widget != cw; cur = cur->next);
  114.  
  115.     if (cur == NULL)
  116.         return;
  117.  
  118.     x = event->xmotion.x_root - 20;
  119.     y = event->xmotion.y_root - 20;
  120.     XtVaSetValues(cur->shell, XtNx, x, XtNy, y, NULL);
  121.  
  122.     XtPopup(cur->shell, XtGrabExclusive);
  123. }
  124.  
  125. static void createItem(Widget parent, PaintMenuItem *item, 
  126.             Widget groups[MAX_GROUPS])
  127. {
  128.     int        grp = -1;
  129.     Widget        entry;
  130.  
  131.     if (item->name[0] == '\0') {
  132.         entry = XtVaCreateManagedWidget("seperator",
  133.                 smeLineObjectClass, parent,
  134.                 NULL);
  135.     } else if (item->flags & MF_CHECK) {
  136.         entry = XtVaCreateManagedWidget(item->name,
  137.                 smeBSBObjectClass, parent,
  138.                 XtNleftMargin, checkmark_width + 4,
  139.                 NULL);
  140.     } else if (item->right != NULL && item->nright != 0) {
  141.         static XtTranslations    trans = None, trans2 = None;
  142.         int            i;
  143.         RightList        *cur;
  144.         String            nm;
  145.  
  146.         if (trans == None) {
  147.             trans = XtParseTranslationTable("<BtnMotion>: highlight() popup-menu-pullright()");
  148.             trans2 = XtParseTranslationTable("<LeaveWindow>: unhighlight() MenuPopdown()\n<BtnUp>: notify() unhighlight() MenuPopdown()\n<BtnMotion>: highlight()");
  149.  
  150.         }
  151.  
  152.         entry = XtVaCreateManagedWidget(item->name,
  153.                 smeBSBObjectClass, parent,
  154.                 XtNrightMargin, pullright_width,
  155.                 XtNrightBitmap, pullBitmap,
  156.                 NULL);
  157.  
  158.         nm = (String)XtMalloc(strlen(XtName(XtParent(parent))) + strlen(item->name) + 16);
  159.         sprintf(nm, "%s-%s-right", XtName(XtParent(parent)), item->name);
  160.  
  161.         item->rightShell = XtVaCreatePopupShell(nm,
  162.                     simpleMenuWidgetClass, parent,
  163.                     XtNtranslations, trans2,
  164.                     NULL);
  165.         XtAddCallback(item->rightShell, XtNdestroyCallback, destroy, (XtPointer)nm);
  166.         XtOverrideTranslations(parent, trans);
  167.  
  168.         for (i = 0; i < item->nright; i++)
  169.             createItem(item->rightShell, &item->right[i], groups);
  170.  
  171.         cur = XtNew(RightList);
  172.         cur->shell = item->rightShell;
  173.         cur->widget = entry;
  174.         cur->next = rightHead;
  175.         rightHead = cur;
  176.     } else {
  177.         entry = XtVaCreateManagedWidget(item->name,
  178.                 smeBSBObjectClass, parent,
  179.                 NULL);
  180.     }
  181.  
  182.     if (item->flags & MF_GROUP1)
  183.         grp = 0;
  184.     else if (item->flags & MF_GROUP2)
  185.         grp = 1;
  186.     else if (item->flags & MF_GROUP3)
  187.         grp = 2;
  188.     else if (item->flags & MF_GROUP4)
  189.         grp = 3;
  190.  
  191.     if (grp != -1) {
  192.         GroupList    *c = findGroup(groups[grp]);
  193.     
  194.         if (c == NULL) {
  195.             /* XXX GroupList entry leaked */
  196.             c = XtNew(GroupList);
  197.             c->next = groupHead;
  198.             groupHead = c;
  199.             c->size = 0;
  200.             groups[grp] = entry;
  201.         }
  202.         c->group[c->size++] = entry;
  203.     }
  204.  
  205.     if ((item->flags & MF_CHECKON) == MF_CHECKON)
  206.         XtVaSetValues(entry, XtNleftBitmap, checkBitmap, NULL);
  207.     
  208.     if (item->callback != NULL)
  209.         XtAddCallback(entry, XtNcallback, item->callback, item->data);
  210.     item->widget = entry;
  211. }
  212.  
  213. Widget MenuBarCreate(Widget parent, int nbar, PaintMenuBar bar[])
  214. {
  215.     int    list, item;
  216.     Widget    button = None, menu;
  217.     Widget    prevButton = None;
  218.     char     menuPopupName[80];
  219.     int    i;
  220.     Widget    groups[MAX_GROUPS];
  221.  
  222.     initMenu(parent);
  223.  
  224.     /*
  225.     **  If there is more than one entry in this bar
  226.     **    reparent it.
  227.     */
  228.     if (nbar > 1) 
  229.         parent = XtVaCreateManagedWidget("menu", 
  230.                 formWidgetClass, parent,
  231.                 XtNborderWidth, 0,
  232.                 XtNbottom, XtChainTop,
  233.                 XtNright, XtChainLeft,
  234.                 XtNleft, XtChainLeft,
  235.                 NULL);
  236.  
  237.     for (list = 0; list < nbar; list++) {
  238.         char        *nm;
  239.         strcpy(menuPopupName, bar[list].name);
  240.         strcat(menuPopupName, "Menu");
  241.  
  242.         nm = XtNewString(menuPopupName);
  243.  
  244.         button = XtVaCreateManagedWidget(bar[list].name, 
  245.                 menuButtonWidgetClass, parent,
  246.                 XtNmenuName,  nm,
  247.                 XtNfromHoriz, prevButton,
  248.                 NULL);
  249.         XtAddCallback(button, XtNdestroyCallback, destroy, (XtPointer)nm);
  250.         prevButton = button;
  251.  
  252.         menu = XtCreatePopupShell(menuPopupName,
  253.                 simpleMenuWidgetClass, button,
  254.                 NULL, 0);
  255.  
  256.         bar[list].widget = menu;
  257.  
  258.         for (i = 0; i < MAX_GROUPS; i++)
  259.             groups[i] = None;
  260.  
  261.         for (item = 0; item < bar[list].nitems; item++)
  262.             createItem(menu, &bar[list].items[item], groups);
  263.     }
  264.  
  265.     return (nbar > 1) ? parent : button;
  266. }
  267.  
  268. Widget MenuPopupCreate(Widget parent, int nitems, PaintMenuItem items[])
  269. {
  270.     static XtTranslations    trans = None;
  271.     int            i;
  272.     Widget            menu;
  273.     Widget        groups[MAX_GROUPS];
  274.  
  275.     for (i = 0; i < MAX_GROUPS; i++)
  276.         groups[i] = None;
  277.  
  278.     initMenu(parent);
  279.  
  280.     menu = XtCreatePopupShell("popup-menu",
  281.             simpleMenuWidgetClass, parent,
  282.             NULL, 0);
  283.  
  284.     if (trans == None)
  285.         trans = XtParseTranslationTable("<Btn3Down>: XawPositionSimpleMenu(popup-menu) MenuPopup(popup-menu)");
  286.     
  287.     XtOverrideTranslations(parent, trans);
  288.  
  289.     for (i = 0; i < nitems; i++) 
  290.         createItem(menu, &items[i], groups);
  291.  
  292.     return menu;
  293. }
  294.  
  295. void MenuCheckItem(Widget w, Boolean flag)
  296. {
  297.     GroupList    *c;
  298.  
  299.     if (w == None)
  300.         return;
  301.  
  302.     if ((c = findGroup(w)) != NULL) {
  303.         int    i;
  304.         for (i = 0; i < c->size; i++)
  305.             XtVaSetValues(c->group[i], XtNleftBitmap, None, NULL);
  306.     }
  307.  
  308.     XtVaSetValues(w, XtNleftBitmap, flag ? checkBitmap : None, NULL);
  309. }
  310.